﻿#region (C) Header Region @ 2012
//====================================================
// 文件: jQueryUtility.cs
// 描述: Ajax工具类
// 路径: Antu.Core\Ajax\jQueryUtility.cs
// ******************版本1 ******************
// 人员: 蔡金保    时间 : 2012/11/15 11:24:07
// 注释:提供注册js功能
//====================================================
#endregion
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Antu.Core.Services;
using Antu.Core.Ajax;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using CainBo.Master;
using System.Web;


namespace Antu.Core.Ajax
{
    /// <summary>
    /// 注册jquery script函数类(该ajax类可用来处理复杂的对象如 List《List《DataTable》》等复杂的对象)，第三方参数为是否异步
    ///<example>
    ///  function aa() {
    ///    antuajax.Default.pushtablea(function (res) {
    ///        alert(res);
    ///    }, function (res) {
    ///       alert("aa");
    ///    },false);
    ///}
    /// </example>
    /// </summary>
    public class AjaxUtility
    {
        public static string AjaxInvokeParam = "AjaxInvoke";
        public static string AjaxInvokeValue = "1";
        public static string ResponseCharset = "UTF-8";
        protected static System.Web.UI.Page Page
        {
            get
            {
                return System.Web.HttpContext.Current.Handler as System.Web.UI.Page;
            }
        }
        protected static bool AutoWriteToHeader = true;
        private static string _invokeScript = "";
        /// <summary>
        /// ajax生成的js代码
        /// </summary>
        public static string InvokeScript
        {
            get
            {
                return _invokeScript;
            }
            set
            {
                _invokeScript = value;
            }
        }

        /// <summary>
        /// 注册ajax，并且自动在header控件中注册
        /// </summary>
        /// <param name="type"></param>
        public static void RegisterClientAjaxScript(Type type)
        {
            RegisterClientAjaxScript(true, type);
        }
        /// <summary>
        /// 注册ajax方法
        /// </summary>
        /// <param name="autowritetoheader">是否需要在header控件中注册</param>
        /// <param name="type"></param>
        public static void RegisterClientAjaxScript(bool autowritetoheader, Type type)
        {
            if (Page != null)
            {
                if (System.Web.HttpContext.Current.Request[AjaxInvokeParam] == AjaxInvokeValue)
                {
                    RegisterAjaxInvokeEvent(type);
                }
                else
                {
                    GetRegisterAjaxInvokeScript(type);
                    if (autowritetoheader)
                    {
                        RegisterAjaxInvokeScript(type);
                    }
                }
            }
        }
        protected static void RegisterAjaxInvokeScript(Type type)
        {
            Header.AddAjaxString(_invokeScript, HttpContext.Current);
        }
        protected static string GetRegisterAjaxInvokeScript(Type type)
        {
            string jsbasestr = "antuajax.";
            if (!UtilityCache.Current.Exists(type))
            {
                MethodInfo[] methodinfoarray = type.GetMethods(System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
                List<MethodInfo> methodinfolist = new List<MethodInfo>();
                for (int temp = 0; temp < methodinfoarray.Length; temp++)
                {
                    object[] attrs = methodinfoarray[temp].GetCustomAttributes(typeof(AjaxMethodAttribute), false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        methodinfolist.Add(methodinfoarray[temp]);
                    }
                }
                MethodInfo[] methodinfo = methodinfolist.ToArray();
                if (methodinfo != null && methodinfo.Length > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int t = 0; t < methodinfo.Length; t++)
                    {
                        ParameterInfo[] parameterinfolist = methodinfo[t].GetParameters();
                        List<string> parameterslist = new List<string>();
                        for (int temp = 0; temp < parameterinfolist.Length; temp++)
                        {
                            parameterslist.Add(parameterinfolist[temp].Name);
                        }
                        var parameters = parameterslist.ToArray();
                        sb.AppendFormat(" " + jsbasestr + "{2}.{0}_ajax = function ({1} Option) {{", methodinfo[t].Name, parameters.Length > 0 ? string.Join(",", parameters) + "," : "", type.Name);
                        sb.Append("if(Option==null||typeof Option=='undefined'){Option={};};");
                        var url = Page.Request.RawUrl.IndexOf("?") == -1 ? Page.Request.RawUrl : Page.Request.RawUrl.Substring(0, Page.Request.RawUrl.IndexOf("?"));
                        sb.AppendFormat("Option.url = '{0}';", url);
                        var data = "''";
                        if (parameters.Length > 0)
                        {
                            List<string> str = new List<string>();
                            for (int index = 0; index < parameters.Length; index++)
                            {
                                str.Add(string.Format("'&{0}=' + {0}+", parameters[index]));
                            }
                            data = string.Join(" ", str.ToArray());
                            data = data.TrimEnd('+');
                        }
                        //if (Page.Request.RawUrl != url)
                        //{
                        //    data += "+'&" + Page.Request.RawUrl.Substring(Page.Request.RawUrl.IndexOf("?") + 1, Page.Request.RawUrl.Length - Page.Request.RawUrl.IndexOf("?") - 1)+"'";
                        //}
                        sb.AppendFormat("Option.data = 'method={1}&rn={4}&{2}={3}'+{0};", data, methodinfo[t].Name, AjaxInvokeParam, AjaxInvokeValue, Guid.NewGuid().ToString());
                        sb.Append("Option= jQuery.extend({type:'GET',cache:false, dataType:'text'},Option);");
                        sb.Append("jQuery.ajax(Option);};");
                        sb.AppendFormat(" " + jsbasestr + "{2}.{0} = function ({1} onsuccess, onerror,onasync) {{if(typeof onasync=='undefined'){{onasync=true;}};", methodinfo[t].Name, parameters.Length > 0 ? string.Join(",", parameters) + "," : "", type.Name);
                        sb.AppendFormat(" " + jsbasestr + "{2}.{0}_ajax({1} ", methodinfo[t].Name, parameters.Length > 0 ? string.Join(",", parameters) + "," : "", type.Name);
                        sb.AppendFormat("{{success: function (res) {{var o = eval(res);onsuccess(o);}}, error: function (res) {{var o = eval(res);onerror(o);return;}},async:onasync,data: antu.toJSON({{}}) }});}};");
                    }
                    UtilityCache.Current.AddScript(type, sb.ToString());
                }
            }
            var script = UtilityCache.Current.GetScript(type);
            string returnstr = "<script type='text/javascript'>antu.registNamespace('" + jsbasestr + "" + type.Name + "');" + script + "</script>";
            _invokeScript = returnstr;
            return returnstr;
        }
        protected static void RegisterAjaxInvokeEvent(Type type)
        {
            var Request = System.Web.HttpContext.Current.Request;
            var Response = System.Web.HttpContext.Current.Response;
            var method = Request["method"];
            if (string.IsNullOrEmpty(method))
                return;
            Response.Clear();
            var methodinfo = type.GetMethod(method, System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            if (methodinfo != null)
            {
                Response.Charset = ResponseCharset;
                Response.ContentType = string.Join(",", Request.AcceptTypes);
                var param = methodinfo.GetParameters();
                object[] objs = new object[param.Length];
                var i = 0;

                for (int temp = 0; temp < param.Length; temp++)
                {
                    objs[i++] = Convert.ChangeType(Request[param[temp].Name], param[temp].ParameterType);
                }
                var obj = methodinfo.Invoke(null, objs);
                SerializerService _SerializerService = (SerializerService)ServiceManager.Manager.GetService(typeof(SerializerService));
                if (obj != null)
                {
                    Response.ContentType = "application/json, text/javascript, */*";
                    Response.Write(_SerializerService.Serialize(obj));
                }

                Response.Flush();
                Response.End();
            }
        }



    }
}
